<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>call、apply、bind</title>
</head>

<body>
    <script>
        // call、apply、bind
        // 函数都可以调用 都是改变this指向的

        // 原生js 实现call方法
        (function () {
            function call(context,) {
                context = context || window;
                // this: sum 也就是当前要操作的函数
                var args = [], res;
                for (var i = 1; i < arguments.length; i++) {
                    args.push(arguments[i])
                }
                // args // 除第一个参数外剩余参数
                context.$fn = this;
                res = context.$fn(...args);
                delete context.$fn;
                return res;
                // return this
            };
            Function.prototype.myCall = call;
        })();

        var obj = {
            name: 'obj'
        }
        var name = 'windows'
        function sum(n, m) {
            console.log(this);
            return n + m
        }
        // sum.myCall(obj, 10, 20);


        (function () {
            Function.prototype.my_call = function (context, ...args) {
                context = context || window;
                context = Object(context)
                context.$fn = this;
                var res = context.$fn(...args);
                delete context.$fn;
                return res;
            }
        })();
        function fn(fn1, num1, num2) {
            // console.log(this.name + fn1);
            return num1 + num2;
        }
        // console.dir(Set)
        var res = fn.call(Set, '参数', 10, 88)
        // console.log(res, 'res');/


        // 阿里面试题
        function fn1() { console.log(1) }
        function fn2() { console.log(2) }
        fn1.call(fn2) // 1 
        fn1.call.call(fn2)
        // 先执行 call(fn2)返回 undefined 
        // 让this指向fn2 然后执行 fn.call() 
        // this为fn2 无参数相当于 
        // 套公式 得出window window.fn2() 打印 2 
        Function.prototype.call(fn1)
        Function.prototype.call.call(fn1)

        // apply 改变函数中this关键字 和call区别传参不一样
        // fn.apply(obj, Array: []参数)
        var obj = { name: 'obj' }
        var name = 'window'
        function fnApply(n, m) {
            console.log(this.name, n + m);
        }
        // fnApply.apply([10, 20], [3, 3])

        // bind 基于bind改变 关键字 当前方法并没有被执行
        // 预先改变this
        document.body.onclick = fn // => this: body
        document.body.onclick = fn.bind(obj) // => this: body

        // 预先做点啥事的思想被成为“柯理化函数”编程思想

        // 获取数组中最大值和最小值
        var num = [1, 3, 4, 55, 3, 54, 22, 9999, 6, 36];
        for (var i = 1; i < num.length; i++) {
            if (num[i] > num[0]) {
                num[0] = num[i];
            }
        }
        console.log(num);
    </script>
</body>

</html>